package org.example;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.experimental.FieldDefaults;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

public class Main {


    static String[] numbers ={"3","4","5","6","7","8","9","10","J","Q","K","A","2","小王","大王"};

    private static int count = 0;
    private static int f = 0;
    private static int s = 0;

    public static void main(String[] args) {
        List<String> fistPoker = ListUtil.of("3","4","5");
        List<String> secondPoker = ListUtil.of("4","4","5");
       // play(getPokerIndex(fistPoker),getPokerIndex(secondPoker));
        Strategy strategy = play2(getPokerIndex(fistPoker),getPokerIndex(secondPoker));
        //strategy.recordToString("");
        initBaseStrategy(strategy);
        System.out.println("结局总数："+count+"失败结局:"+f+"胜利结局:"+s+"先手是否必胜:"+!strategy.isBaste);
        if(!strategy.isBaste){
            strategy.printBast("");
        }
    }




    private static List<Integer> getPokerIndex(List<String> pokers){
        List<Integer> pokerIndex = new ArrayList<Integer>();
        pokers.forEach(poker ->{
            for (int i = 0; i < 15; i++) {
                if(poker.equals(numbers[i])){
                    pokerIndex.add(i);
                }
            }
        });
        return pokerIndex;
    }

    private static Strategy play2(List<Integer> fist, List<Integer> second){
        Strategy build = Strategy.builder().build();
        build.strategies = strategy(-1,fist,second,true);
        build.strategies.forEach(Main::play3);
        return build;
    }


    private static void play3(Strategy strategy){
        if(strategy.type == 0){
            strategy.strategies = strategy(strategy.thisPoker,strategy.analoguePoker,strategy.residuePoker,!strategy.user);
        }else {
            strategy.strategies = strategy(-1,strategy.analoguePoker,strategy.residuePoker,!strategy.user);
        }
        strategy.strategies.forEach(e->{
            if(CollUtil.isNotEmpty(e.residuePoker)){
                play3(e);
            }else {
                if(e.user){
                    s=s+1;
                }else{
                    f=f+1;
                }
                count = count+1;
            }
        });
    }


    /**
     * 获取最佳对弈策略
     * @return
     */
    private static void initBaseStrategy(Strategy strategy){
        if(CollUtil.isEmpty(strategy.strategies)){
            strategy.isBaste = true;
            return;
        }
        strategy.strategies.forEach(Main::initBaseStrategy);
        strategy.isBaste = strategy.strategies.stream().noneMatch(e->e.isBaste);
    }

    /**
     * 获取应对策略
     * @param poker
     * @param pokers
     * @return
     */
    private static List<Strategy> strategy(Integer poker,List<Integer> pokers,List<Integer> analoguePoker,Boolean user){
        List<Strategy> records = new ArrayList<Strategy>();
        for(Integer thisPock:pokers){
            if(thisPock>poker){
                records.add(Strategy.builder().type(0).residuePoker(residuePoker(pokers,thisPock)).user(user).analoguePoker(analoguePoker).thisPoker(thisPock).build());
            }
        }
        if(records.size()<1){
            records.add(Strategy.builder().type(2).residuePoker(pokers).analoguePoker(analoguePoker).user(user).build());
        }else if(poker!=-1){
            records.add(Strategy.builder().type(1).residuePoker(pokers).analoguePoker(analoguePoker).user(user).build());
        }
        return records;
    }

    /**
     * 获取剩余的牌
     */
    private static List<Integer> residuePoker(List<Integer> pokers,Integer poker){
        List<Integer> residue = new ArrayList<Integer>();
        pokers.forEach(e->{
            if(!e.equals(poker)){
                residue.add(e);
            }
        });
        return residue;
    }

    @Builder
    @FieldDefaults(level = AccessLevel.PUBLIC)
    static class Strategy{
        /**
         * true先手false后手
         */
        Boolean user;
        /**
         * 0 出牌
         * 1 过牌
         * 2 要不起
         */
        Integer type;

        /**
         * 出牌
         */
        Integer thisPoker;
        /**
         * 是否最佳策略
         */
        Boolean isBaste;
        /**
         * 剩余手牌
         */
        List<Integer> residuePoker;
        /**
         * 对手牌
         */
        List<Integer> analoguePoker;

        /**
         * 子策略
         */
        List<Strategy> strategies;

        private void recordToString(String str){
            if(user ==null){

            } else if(user){
                str = str + "玩家1:";
            } else if(!user){
                str = str + "玩家2:";
            }
            if(type == null){
            } else if(type == 0){
                str = str+numbers[thisPoker]+",";
            }else if(type == 1){
                str = str+"过"+",";
            }else if(type==2){
                str = str+"要不起"+",";
            }
            if(CollUtil.isNotEmpty(strategies)){
                String finalStr = str;
                strategies.forEach(record1 -> record1.recordToString(finalStr));
            }else {
                System.out.println(str+(user?"胜":"败"));
            }
        }

        private void printBast(String str){
            if(user ==null){

            } else if(user){
                if(!isBaste){
                    return;
                }
                str = str + "玩家1:";
            } else if(!user){
                if(isBaste){
                    return;
                }
                str = str + "玩家2:";
            }
            if(type == null){
            } else if(type == 0){
                str = str+numbers[thisPoker]+",";
            }else if(type == 1){
                str = str+"过"+",";
            }else if(type==2){
                str = str+"要不起"+",";
            }
            if(CollUtil.isNotEmpty(strategies)){
                String finalStr = str;
                strategies.forEach(record1 -> record1.printBast(finalStr));
            }else {
                System.out.println(str+(user?"胜":"败"));
            }
        }
    }



}